// Copyright (C) 2011 YANG Hao (yangh2007@gmail.com). All rights reserved.
//
// This file is part of the (cute)octopus project.
//
// This file may be distributed and/or modified under the terms of the
// GNU General Public License version 2 as published by the Free Software
// Foundation.
//
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
//
// Author(s): YANG Hao


#include "oapplication.h"

#include <QtGui/QMainWindow>
#include <QFileDialog>
#include <QLabel>
#include <QMessageBox>
#include <QMdiArea>
#include <QMdiSubWindow>
#include <QMenu>
#include <QMenuBar>
#include <QPainter>
#include <QProgressBar>
#include <QStatusBar>
#include <QToolBar>

#include <QItemEditorFactory>
#include <QCheckBox>
#include <QDateEdit>
#include <QDateTimeEdit>
#include <QDoubleSpinBox>
#include <QLineEdit>
#include <QSpinBox>
#include <QTimeEdit>

#include "oevent.h"
#include "odescriptors.h"
#include "ocreator.h"
#include "odoc.h"
#include "oproperty.h"
#include "otask.h"
#include "owindow.h"

using namespace OStd;

PRIVATE_BEGIN()
class OProgressBar;

// OMainWindow
class OMainWind : public QMainWindow
{
	Q_OBJECT

	typedef QMessageBox::StandardButton Button;
	enum {
		Yes = QMessageBox::Yes, 
		No = QMessageBox::No, 
		Cancel = QMessageBox::Cancel
	};

public:
	OMainWind(QWidget *parent = 0, Qt::WFlags flags = 0);
	~OMainWind();

	inline void initEditors();
	inline void createStatusBar();
	inline void createMdiWindow();
	inline void createActions();
	inline void createToolBars();
	inline void createMenus();
	inline void createDockWidgets();

public slots:
	inline void newFile();
	inline void openFile();
	inline void saveFile();
	inline void saveAsFile();
	inline void tabView(bool on);
	inline void refresh();
	inline void help();
	inline void about(){}

	inline void onSubWindowActivated(QMdiSubWindow*);

protected:
	virtual bool event(QEvent* event);
	virtual void closeEvent(QCloseEvent* event);

public:
	inline void initFiles(const QStringList& files);
	inline void progressBegin(OTaskAsync* t);
	inline void progressNotify(OEvent* m);
	inline void progressEnd(OEvent* m);

	inline ODoc* createDoc(const QString& filePath);
	inline OWindow* createSubWindow(ODoc* doc);
	inline OWindow* appendSubWindow(ODoc* doc);	
	inline void activateSubWindow(OWindow* window);

	inline void refreshActions();

	inline QString saveFileName(const QString& initName = QString()) const;
	inline QStringList openFileNames(const QString& initName = QString()) const;
	
	inline Button questionSaveDoc(const QString& name) const{return Button(Yes);}// TODO

public:
	QLabel* m_mouseStatus;
	QLabel* m_toolStatus;

	QMap<OTaskAsync*, OProgressBar*> m_progresses;
	QMap<QString, ODoc*> m_docs;

	QMdiArea* m_mdiArea;
	QMenuBar* m_menuBar;
	
	//QToolBar* m_comToolbars[MWindowToolBarCount];
	//QAction* m_comActs[MWindowActionCount];
	//QMenu* m_comMenus[MWindowMenuCount];
	//QDockWidget* m_comDocks[MWindowDockCount];

	QMap<QString, QToolBar*> m_comToolbars;
	QMap<QString, QMenu*> m_comMenus;
	QMap<QString, QDockWidget*> m_comDocks;
};



// OProgressBar
class OProgressBar : public QProgressBar
{
public:
	OProgressBar(QWidget *parent = 0){}
	~OProgressBar(){}
	inline void setInfoText(const QString& t){m_text = t;}
protected:
	virtual void paintEvent(QPaintEvent* e){
		QProgressBar::paintEvent(e);
		QPainter p(this);
		p.drawText(4, height() - 4, m_text);
	}
private:
	QString m_text;
};




// OMainWind implementation
OMainWind::OMainWind(QWidget *parent, Qt::WFlags flags)
	: QMainWindow(parent, flags)
{	
	initEditors();

	createMdiWindow();
	createStatusBar();
	createActions();
	createMenus();
	createToolBars();
	createDockWidgets();

	// open files assigned by command line arguments
	QStringList args = QCoreApplication::arguments();
	args.removeFirst();
	initFiles(args);

	
}

OMainWind::~OMainWind()
{
	foreach(ODoc* d, m_docs.values())
		d->deleteLater();
}

class OIntEditor : public QSpinBox {
public:
	OIntEditor(QWidget* parent = 0):QSpinBox(parent){setRange(-5000, 5000);}
};
class ODoubleEditor : public QDoubleSpinBox {
public:
	ODoubleEditor(QWidget* parent = 0):QDoubleSpinBox(parent){
		setRange(-5000, 5000); setDecimals(8); setSingleStep(0.1);
	}
};

void OMainWind::initEditors()
{
	QItemEditorFactory *factory = new QItemEditorFactory;		
	//factory->registerEditor(QVariant::Color, new QStandardItemEditorCreator<ColorListEditor>());
	factory->registerEditor(QVariant::Int, new QStandardItemEditorCreator<OIntEditor>());
	factory->registerEditor(QVariant::Double, new QStandardItemEditorCreator<ODoubleEditor>());
	//factory->registerEditor(QVariant::Float, new QStandardItemEditorCreator<QDoubleSpinBox>());
	factory->registerEditor(QVariant::String, new QStandardItemEditorCreator<QLineEdit>());
	factory->registerEditor(QVariant::Time, new QStandardItemEditorCreator<QTimeEdit>());
	factory->registerEditor(QVariant::Date, new QStandardItemEditorCreator<QDateEdit>());
	factory->registerEditor(QVariant::DateTime, new QStandardItemEditorCreator<QDateTimeEdit>());
	//factory->registerEditor(QVariant::StringList, new QStandardItemEditorCreator<StringListEditButton>());
	factory->registerEditor(QVariant::Bool, new QStandardItemEditorCreator<QCheckBox>());
	//factory->registerEditor(QVariant::Vector3D, new QStandardItemEditorCreator<Vector3DEdit>());
	QItemEditorFactory::setDefaultFactory(factory);
}

void OMainWind::createStatusBar()
{
	QStatusBar* bar = statusBar();

	m_mouseStatus = new QLabel();
	m_mouseStatus->setText(tr("mouse location"));
	bar->addPermanentWidget(m_mouseStatus);
	m_mouseStatus->setMinimumSize(m_mouseStatus->sizeHint());

	m_toolStatus = new QLabel();
	m_toolStatus->setText(tr("tool status"));
	bar->addPermanentWidget(m_toolStatus);
	m_toolStatus->setMinimumSize(m_toolStatus->sizeHint());
	
	bar->showMessage(tr("Ready"));	
	bar->setMaximumHeight(bar->height());
}

void OMainWind::createMdiWindow()
{
	m_mdiArea = new QMdiArea;
	//m_mdiArea->setDocumentMode(true);
	m_mdiArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
	m_mdiArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
	//m_mdiArea->findChild<QTabBar*>()->setElideMode(Qt::ElideRight);
	//m_mdiArea->findChild<QTabBar*>()->setMovable(false);
	//m_mdiArea->findChild<QTabBar*>()->setDrawBase(true);
	QLinearGradient linearGrad(QPointF(100, 100), QPointF(800, 800));
	linearGrad.setColorAt(0, QColor(60, 60, 60));
	linearGrad.setColorAt(1, QColor(90, 90, 100));
	m_mdiArea->setBackground(linearGrad);

	setCentralWidget(m_mdiArea);
	//m_mdiArea->addSubWindow(new QWidget());

	connect(m_mdiArea, SIGNAL(subWindowActivated(QMdiSubWindow*)), 
		this, SLOT(onSubWindowActivated(QMdiSubWindow*)));
}

void OMainWind::createActions()
{
	m_comActs[Action_New] = new QAction(QIcon(":/omainwind/toolbar/Resources/toolbar-icons/Add.png"), tr("&New"), this);
	m_comActs[Action_New]->setShortcuts(QKeySequence::New);
	m_comActs[Action_New]->setStatusTip(tr("Create a new file"));
	connect(m_comActs[Action_New], SIGNAL(triggered()), this, SLOT(newFile()));

	m_comActs[Action_Open] = new QAction(QIcon(":/omainwind/toolbar/Resources/toolbar-icons/Load.png"), tr("&Open..."), this);
	m_comActs[Action_Open]->setShortcuts(QKeySequence::Open);
	m_comActs[Action_Open]->setStatusTip(tr("Open an existing file"));
	connect(m_comActs[Action_Open], SIGNAL(triggered()), this, SLOT(openFile()));

	m_comActs[Action_Save] = new QAction(QIcon(":/omainwind/toolbar/Resources/toolbar-icons/Save.png"), tr("&Save"), this);
	m_comActs[Action_Save]->setShortcuts(QKeySequence::Save);
	m_comActs[Action_Save]->setStatusTip(tr("Save the document to disk"));
	connect(m_comActs[Action_Save], SIGNAL(triggered()), this, SLOT(saveFile()));

	m_comActs[Action_SaveAs] = new QAction(QIcon(":/omainwind/toolbar/Resources/toolbar-icons/Save As.png"), tr("Save &As..."), this);
	m_comActs[Action_SaveAs]->setShortcuts(QKeySequence::SaveAs);
	m_comActs[Action_SaveAs]->setStatusTip(tr("Save the document under a new name"));
	connect(m_comActs[Action_SaveAs], SIGNAL(triggered()), this, SLOT(saveAsFile()));

	m_comActs[Action_TabView] = new QAction(QIcon(":/omainwind/toolbar/Resources/toolbar-icons/Tab.png"), tr("&Tab View"), this);
	m_comActs[Action_TabView]->setStatusTip(tr("Switch tab view mode"));
	m_comActs[Action_TabView]->setCheckable(true);
	m_comActs[Action_TabView]->setChecked(false);
	connect(m_comActs[Action_TabView], SIGNAL(triggered(bool)), this, SLOT(tabView(bool)));

	m_comActs[Action_CascadeSubWindows] = new QAction(QIcon(":/omainwind/toolbar/Resources/toolbar-icons/Cascade.png"), tr("&Cascade"), this);
	m_comActs[Action_CascadeSubWindows]->setStatusTip(tr("Cascade SubWindows"));
	connect(m_comActs[Action_CascadeSubWindows], SIGNAL(triggered()), m_mdiArea, SLOT(cascadeSubWindows()));

	m_comActs[Action_TileSubWindows] = new QAction(QIcon(":/omainwind/toolbar/Resources/toolbar-icons/Tile.png"), tr("&Tile"), this);
	m_comActs[Action_TileSubWindows]->setStatusTip(tr("Tile SubWindows"));
	connect(m_comActs[Action_TileSubWindows], SIGNAL(triggered()), m_mdiArea, SLOT(tileSubWindows()));

	m_comActs[Action_Refresh] = new QAction(O_DEVELOP_ICON, tr("&Refresh"), this);
	m_comActs[Action_Refresh]->setToolTip(tr("Refresh Widget"));
	connect(m_comActs[Action_Refresh], SIGNAL(triggered()), this, SLOT(refresh()));

	m_comActs[Action_Exit] = new QAction(QIcon(":/omainwind/toolbar/Resources/toolbar-icons/Exit.png"), tr("E&xit"), this);
	m_comActs[Action_Exit]->setShortcuts(QKeySequence::Quit);
	m_comActs[Action_Exit]->setStatusTip(tr("Exit the application"));
	connect(m_comActs[Action_Exit], SIGNAL(triggered()), this, SLOT(close()));

	m_comActs[Action_About] = new QAction(QIcon(":/omainwind/toolbar/Resources/toolbar-icons/Info.png"), tr("A&bout"), this);
	m_comActs[Action_About]->setStatusTip(tr("Show the application's About box"));
	connect(m_comActs[Action_About], SIGNAL(triggered()), this, SLOT(about()));

	m_comActs[Action_Help] = new QAction(QIcon(":/omainwind/toolbar/Resources/toolbar-icons/Profile.png"), tr("&Help"), this);
	m_comActs[Action_Help]->setShortcuts(QKeySequence::HelpContents);
	m_comActs[Action_Help]->setStatusTip(tr("Show the application's Help content"));
	connect(m_comActs[Action_Help], SIGNAL(triggered()), this, SLOT(help()));
}

void OMainWind::createMenus()
{
	m_comMenus[Menu_File] = menuBar()->addMenu(tr("&File"));
	//m_comMenus[MM_File]->addAction(m_comActs[MA_New]);
	m_comMenus[Menu_File]->addAction(m_comActs[Action_Open]);
	//m_comMenus[MM_File]->addSeparator();
	//m_comMenus[MM_File]->addAction(m_comActs[MA_Save]);
	//m_comMenus[MM_File]->addAction(m_comActs[MA_SaveAs]);
	m_comMenus[Menu_File]->addSeparator();
	
	//QList<QAction*> actions = oCreator()->actions();
	//if(!actions.empty()){
	//	m_comMenus[MM_File]->addActions(actions);
	//	m_comMenus[MM_File]->addSeparator();
	//}
	m_comMenus[Menu_File]->addAction(m_comActs[Action_Exit]);

	m_comMenus[Menu_Tools] = menuBar()->addMenu(tr("&Tools"));
	m_comMenus[Menu_Tools]->menuAction()->setVisible(false);

	m_comMenus[Menu_View] = menuBar()->addMenu(tr("&View"));
	m_comMenus[Menu_View]->addAction(m_comActs[Action_TabView]);
	m_comMenus[Menu_View]->addAction(m_comActs[Action_CascadeSubWindows]);
	m_comMenus[Menu_View]->addAction(m_comActs[Action_TileSubWindows]);
	
	
	m_comMenus[Menu_Help] = menuBar()->addMenu(tr("&Help"));
	m_comMenus[Menu_Help]->addAction(m_comActs[Action_About]);
	m_comMenus[Menu_Help]->addAction(m_comActs[Action_Help]);
}

void OMainWind::createToolBars()
{
	m_comToolbars[ToolBar_Standard] = new QToolBar(tr("ToolBar - Standard"), this);
		addToolBar(Qt::LeftToolBarArea, m_comToolbars[ToolBar_Standard]);
	//m_comToolbars[MT_Std]->addAction(m_comActs[MA_New]);
	m_comToolbars[ToolBar_Standard]->addAction(m_comActs[Action_Open]);
	//m_comToolbars[MT_Std]->addAction(m_comActs[MA_Save]);
	//m_comToolbars[MT_Std]->addAction(m_comActs[MA_SaveAs]);
	//m_comToolbars[MT_Std]->addSeparator();
	m_comToolbars[ToolBar_Standard]->addAction(m_comActs[Action_Help]);
	//m_comToolbars[MT_Std]->hide();


	m_comToolbars[ToolBar_Widget] = new QToolBar(tr("ToolBar - Widget"), this);
	addToolBar(Qt::LeftToolBarArea, m_comToolbars[ToolBar_Widget]);
	m_comToolbars[ToolBar_Widget]->hide();

	m_comToolbars[ToolBar_View] = new QToolBar(tr("ToolBar - View"), this);
		addToolBar(Qt::LeftToolBarArea, m_comToolbars[ToolBar_View]);
	m_comToolbars[ToolBar_View]->addAction(m_comActs[Action_TabView]);
	m_comToolbars[ToolBar_View]->addAction(m_comActs[Action_CascadeSubWindows]);
	m_comToolbars[ToolBar_View]->addAction(m_comActs[Action_TileSubWindows]);
	//m_comToolbars[MT_View]->addAction(m_comActs[MA_Refresh]);


	//QList<QAction*> actions = oCreator()->actions();
	//if(!actions.empty()){
	//	m_comToolbars[MT_Creator] = new QToolBar(tr("ToolBar - Creator"), this);
	//		addToolBar(Qt::LeftToolBarArea, m_comToolbars[MT_Creator]);
	//	m_comToolbars[MT_Creator]->addActions(actions);
	//	//m_comToolbars[MT_Creator]->setOrientation(Qt::Vertical);
	//}

}

void OMainWind::createDockWidgets()
{
	m_comDocks[Dock_Property] = new OPropertyDock(this);
	//m_comDocks[MD_Property]->setFloating(true);
	addDockWidget(Qt::RightDockWidgetArea, m_comDocks[Dock_Property]);
}

void OMainWind::initFiles(const QStringList& fileNames)
{
	if(fileNames.empty())
		return;
	OCreator* creator = oCreator();
	OTaskAsync* openTask = creator->openTask();
	OWindow* window = 0;
	foreach(QString fileName, fileNames){
		ODoc* doc = createDoc(fileName);
		window = createSubWindow(doc);
		openTask->addDoc(doc);
		activateSubWindow(window);
	}
	oApp()->execTask(openTask);
}

inline void OMainWind::progressBegin( OTaskAsync* t )
{
	if(!m_progresses.contains(t)){
		OProgressBar* progBar = new OProgressBar;
		progBar->setMaximumSize(250, statusBar()->height()-5);
		progBar->setRange(0, 0);
		m_progresses.insert(t, progBar);
		statusBar()->addPermanentWidget(m_progresses.value(t));
	}
}

void OMainWind::progressNotify(OEvent* m)
{
	if(!m_progresses.contains(m->sender()))
		progressBegin(m->sender());
	if(m->progress() < 0)
		m_progresses.value(m->sender())->setRange(0, 0);
	else{
		m_progresses.value(m->sender())->setRange(0, 100);
		m_progresses.value(m->sender())->setValue(100 * m->progress());
	}
	m_progresses.value(m->sender())->setInfoText(m->text());
}

void OMainWind::progressEnd(OEvent* m)
{
	if(m_progresses.contains(m->sender())){
		statusBar()->removeWidget(m_progresses.value(m->sender()));
		m_progresses.value(m->sender())->deleteLater();
		m_progresses.remove(m->sender());
	}
	m->sender()->onFinish();
}
	

bool OMainWind::event(QEvent* event)
{
	if(event->type() < QEvent::User)
		return QMainWindow::event(event);
	OEvent* m = static_cast<OEvent*>(event);
	switch(m->type()){
		case OStd::Event_TaskStarted:
			progressBegin(m->sender());
			break;
		case OStd::Event_TaskStopped:
			progressEnd(m);
			break;
		case OStd::Event_TaskNotify:
			progressNotify(m);
			break;
		default:
			break;
	}
	return true;
}

void OMainWind::closeEvent(QCloseEvent* event)
{
	// TODO: add save checking
	QMainWindow::closeEvent(event);
}

// create doc from a given file
ODoc* OMainWind::createDoc(const QString& filePath)
{
	QString stdFilePath = QFileInfo(filePath).filePath();
	if(m_docs.contains(stdFilePath))
		return m_docs.value(stdFilePath);
	ODoc* doc = oCreator()->createDoc(stdFilePath);
	m_docs.insert(stdFilePath, doc);
	return doc;
}

// check before adding
OWindow* OMainWind::createSubWindow(ODoc* doc)
{
	if(doc->hasWindows())
		return doc->windowAt(0);
	return appendSubWindow(doc);
}

// add a new subwindow for the doc
OWindow* OMainWind::appendSubWindow(ODoc* doc)
{
	OWindow* subWindow = new OWindow(doc);
	QWidget* widget = oCreator()->createWidget(doc);
	subWindow->setWidget(widget);
	widget->installEventFilter(subWindow);
	m_mdiArea->addSubWindow(subWindow);
	return subWindow;
}

void OMainWind::refreshActions()
{
	OWindow* curWind = dynamic_cast<OWindow*>(m_mdiArea->currentSubWindow());
	if(curWind){
		QList<QAction*> actions = curWind->widget()->actions();
		if(!actions.empty()){
			if(!m_comToolbars[ToolBar_Widget]){
				m_comToolbars[ToolBar_Widget] = new QToolBar(tr("ToolBar - ") + curWind->widget()->objectName(), this);
					addToolBar(Qt::LeftToolBarArea, m_comToolbars[ToolBar_Widget]);
			}else
				m_comToolbars[ToolBar_Widget]->setWindowTitle(tr("ToolBar - ") + curWind->widget()->objectName());
			m_comToolbars[ToolBar_Widget]->clear();
			m_comToolbars[ToolBar_Widget]->addActions(actions);
			m_comToolbars[ToolBar_Widget]->show();

			if(!m_comMenus[Menu_Tools])
				m_comMenus[Menu_Tools] = menuBar()->addMenu(tr("Tools"));
			m_comMenus[Menu_Tools]->clear();
			m_comMenus[Menu_Tools]->addActions(actions);
			m_comMenus[Menu_Tools]->menuAction()->setVisible(true);
		}
	}else if(m_comToolbars[ToolBar_Widget]){
		//removeToolBar(m_comToolbars[MT_Widget]);
		m_comToolbars[ToolBar_Widget]->hide();
		m_comMenus[Menu_Tools]->menuAction()->setVisible(false);
	}
}

void OMainWind::activateSubWindow(OWindow* window)
{
	window->showMaximized();
	refreshActions();
}

QString OMainWind::saveFileName(const QString& initName) const
{
	return QFileDialog::getSaveFileName(0, 
		QObject::tr("Save File to..."), initName, oCreator()->filters());
}

QStringList OMainWind::openFileNames(const QString& initName) const
{
	return QFileDialog::getOpenFileNames(0, 
		QObject::tr("Open Files"), initName, oCreator()->filters());
}



void OMainWind::newFile()
{
	OCreator* creator = oCreator();
	QList<ODocDescriptor*>& formats = creator->formats();
	Q_ASSERT(!formats.empty());

	ODoc* doc = createDoc(formats[0]->unnamedSample()); // TODO: chooser for multi-formats
	OWindow* window = appendSubWindow(doc);
	activateSubWindow(window);
}

void OMainWind::openFile()
{
	OCreator* creator = oCreator();
	QStringList fileNames = openFileNames();
	if(fileNames.empty())
		return;
	OTaskAsync* openTask = creator->openTask();
	OWindow* window = 0;
	foreach(QString fileName, fileNames){
		ODoc* doc = createDoc(fileName);
		window = createSubWindow(doc);
		openTask->addDoc(doc);
		activateSubWindow(window);
	}
	oApp()->execTask(openTask);		
}

void OMainWind::saveFile()
{
	ODoc* curDoc = oApp()->currentDoc();
	if(!curDoc || curDoc->isReadOnly())
		return;

	if(curDoc->notExist())
		saveAsFile();
	else{
		// start saving task
		OTaskAsync* saveTask = oCreator()->saveTask();
		saveTask->setDoc(curDoc);
		oApp()->execTask(saveTask);
	}
}

void OMainWind::saveAsFile()
{
	ODoc* curDoc = oApp()->currentDoc();
	if(!curDoc || curDoc->isReadOnly())
		return;

	OCreator* creator = oCreator();
	QString fileName = saveFileName(curDoc->filePath());
	if(fileName.isEmpty())
		return;
	curDoc->setResource(fileName);

	// start saving task
	OTaskAsync* saveTask = creator->saveTask();
	saveTask->setDoc(curDoc);
	oApp()->execTask(saveTask);
}

void OMainWind::tabView(bool on)
{
	m_mdiArea->setViewMode(on ? QMdiArea::TabbedView : QMdiArea::SubWindowView);
}

void OMainWind::refresh()
{
	oApp()->currentWindow()->widget()->repaint();
}

void OMainWind::help()
{

}

void OMainWind::onSubWindowActivated(QMdiSubWindow* w)
{
	QWidget* widget = 0;
	if(w && (widget = w->widget()))
		oCreator()->widgetActivated(widget);
	else
		oCreator()->widgetActivated(0);
	refreshActions();
}

//bool OMainWind::onSubWindowClosed(QMdiSubWindow* w)
//{
//
//	return true;
//}

#include "oapplication.moc"



OMainWind* _mwind;
OCreator* _creator;
inline void _Init(){_mwind = 0; _creator = 0;}
inline void _Release(){delete _mwind; delete _creator;}
PRIVATE_END()



OApplication::OApplication(int & argc, char ** argv)
	: QApplication(argc, argv)
{OPrivate::_Init();}

OApplication::~OApplication()
{OPrivate::_Release();}

QMainWindow* OApplication::mainWindow() const {return OPrivate::_mwind;}
OCreator* OApplication::creator() const {return OPrivate::_creator;}

int OApplication::exec(OCreator* c) {
	OPrivate::_creator = c;
	OPrivate::_mwind = new OPrivate::OMainWind;

	OPrivate::_mwind->setWindowIcon(OPrivate::_creator->icon());
	OPrivate::_mwind->setWindowTitle(OPrivate::_creator->name());
	//m_mwind->resize(600, 650);

	OPrivate::_mwind->show(); 
	return QApplication::exec();
}

OWindow* OApplication::currentWindow() const
{
	return dynamic_cast<OWindow*>(OPrivate::_mwind->m_mdiArea->currentSubWindow());
}

ODoc* OApplication::currentDoc() const
{
	OWindow* curWindow = currentWindow();
	return curWindow ? curWindow->doc() : 0;
}

// obsolete
ODoc* OApplication::doc(const QString& filePath) const
{
	return OPrivate::_mwind->m_docs.value(filePath, 0);
}

QList<ODoc*> OApplication::allDocs() const
{
	return OPrivate::_mwind->m_docs.values();
}

ODoc* OApplication::openDoc(const QString& filePath)
{
	ODoc* doc = OPrivate::_mwind->createDoc(filePath);
	OPrivate::_mwind->activateSubWindow(OPrivate::_mwind->createSubWindow(doc));
	return doc;
}

void OApplication::closeDoc(const QString& filePath)
{
	ODoc* doc = OPrivate::_mwind->m_docs.value(filePath, 0);
	if(doc){
		OPrivate::_mwind->m_docs.remove(filePath);
		doc->deleteLater();
	}
}

QList<OTaskAsync*> OApplication::runningTasks() const
{
	return OPrivate::_mwind->m_progresses.keys();
}

void OApplication::sendMessageToMainWind(OEvent* message) const
{
	QObject* m = dynamic_cast<QObject*>(OPrivate::_mwind);
	QCoreApplication::sendEvent(dynamic_cast<QObject*>(OPrivate::_mwind), 
		static_cast<QEvent*>(message));
}

void OApplication::postMessageToMainWind(OEvent* message) const
{	
	QObject* m = dynamic_cast<QObject*>(OPrivate::_mwind);
	QCoreApplication::postEvent(dynamic_cast<QObject*>(OPrivate::_mwind), 
		static_cast<QEvent*>(message), Qt::HighEventPriority + 1);
}

void OApplication::postMessageToWidget(OEvent* message, QWidget* w) const
{
	QCoreApplication::postEvent(dynamic_cast<QObject*>(w), 
		static_cast<QEvent*>(message), Qt::HighEventPriority + 1);
}

void OApplication::postMessageToCreator(OEvent* message) const
{
	QCoreApplication::postEvent(dynamic_cast<QObject*>(OPrivate::_creator), 
		static_cast<QEvent*>(message));
}

bool OApplication::execTask(OTaskAsync* task)
{
	if(!task)
		return false;
	if(!task->tryTakingUpDocs()){
		QMessageBox::warning(OPrivate::_mwind, tr("Document Inoperable"), 
			tr("Sorry but some previous tasks on this document have not finished yet. "
			   "I'm afraid this invocation shall be abandoned."));
		return false;
	}
	task->onStart();
	task->start();
	return true;
}

void OApplication::updateStatus(const QString& text, OStd::WindowStatusPosition position)
{
	switch(position){
		case OStd::Position_CurrentTool: OPrivate::_mwind->m_toolStatus->setText(text); break;
		case OStd::Position_MouseLocation: OPrivate::_mwind->m_mouseStatus->setText(text); break;
		default: break;
	}	
}